//{=============================================================================================================
//! @file SGLib.h
//! @brief SGLibrary3D - новая версия SGLib с поддержкой 3D.
//! 
//! Билиотека была разработана для тех кому режет глаза обычный код OpenGL,@startcross юных подаванов@endcross,
//! и для последующего применения в различных проектов.
//! 
//! $ Author: Andrew Bezzubtsev(void)$
//! $ Date: 22.01.2015 17:31 GTM +0400$
//! $ Version: 3.0$
//! $ Revision: 12$
//! 
//! @Warning Для корректной работы надо создать OpenGL проект$
//! 
//}=============================================================================================================

#ifndef SGLIB_H_INCLUDED
#define SGLIB_H_INCLUDED

#include <windows.h>

#include <GL/gl.h>
#include <GL/glu.h>

#include <locale.h>

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include <conio.h>
#include <vector>
                      
#if _WIN32_WINNT < 0x0500
	#undef  _WIN32_WINNT
	#define _WIN32_WINNT   0x0500
#endif
  
#ifdef __TXLIB_H
        #define GetStockObject Win32::GetStockObject
#endif

//{=============================================================================================================
//! @defgroup Macros Макросы
//! @defgroup NamespaceConst Константы и пространства имен
//! @defgroup Error Ошибки
//! @defgroup Drawing Рисование
//! @defgroup Color Цвета
//}=============================================================================================================

//{=============================================================================================================
//! @ingroup Macros
//! @brief MIN Macros
//! Возвращает минимальное из чисел
//! @param a Первое число
//! @param b Второе число
//! 
//! @code
//! int x = 500, y = 40, c = MIN(x, y); 
//! @endcode
//}=============================================================================================================

#define MIN(a, b) (((a) < (b))? (a) : (b))

//{=============================================================================================================
//! @ingroup Macros 
//! @brief MAX Macros
//! Возвращает большее из чисел
//! @param a Первое число
//! @param b Второе число
//!
//! @code 
//! int x = 500, y = 40, c = MAX(x, y);
//! @endcode
//}=============================================================================================================

#define MAX(a, b) (((a) > (b))? (a) : (b))

//{=============================================================================================================
//! @ingroup NamespaceConst
//! @brief Пространство имен окна.
//! Здесь храняться многие данные окна, юный подаван...
//! 
//}============================================================================================================= 

namespace SGWindow
{                
	int width,                            //!< Размер "холста" по x. Если его просто поменять, окно не измениться 
	    height;                           //!< Размер "холста" по y. Если его просто поменять, окно не измениться!

    	int WindowSx,                         //!< Реальный размер окна по x. Нужен для верного отображения рабочей области окна.
            WindowSy; 	                      //!< Реальный размер окна по y. Нужен для верного отображения рабочей области окна.

    	bool WindowRun = false;               //!< Открыто окно, или нет. Лучше не менять, если не знаете где будете. @startcrossУ нас живут котики@endcross
    	bool OpenGLRun = false;               //!< Запущен OpenGl, или нет. Насчет изменения смотри строкой выше... ^-^

    	HWND   SGWnd;                         //!< Дескриптор окна
    	HDC    SGDC;                          //!< Холст окна
    	HGLRC  SGRc;                          //!< RC окна

    	int win_x_pos,                        //!< Координата x окна (верхний левый угол)
            win_y_pos;                        //!< Координата y окна (верхний левый угол)

        const char WinDefTitle [ ] = "SGLib.h - (C), Andrew Bezzubtsev (OpenGL-based)"; //!< Стандартный заголовок.
}

namespace SGWindowParams
{
	HWND  WND;
	HDC   DC;
	HGLRC RC;
}

namespace SGUser
{
    	bool ExitAfterClose = true; //!< После закрытия окна выходить, или нет
    	bool Rusificate     = true; //!< Русификацировать ли нам консольку??? консоли окна.
    	bool VisibleClear   = true; //!< Включает или выключает обновление экрана после @ref exClear ()
    	bool DepthTest      = true; //!< Включает или выключает тест глубины. Если используете SGLib только не для 3D поставьте false
}

namespace SGParams
{
   	bool ScreenFreeze  = false; //!< Блокировка обновления окна.
   	int  sgBeginNumber = 0;     //!< Считает кол-во вызванных @ref sgBegin()

    	bool Textures      = false; //!< Немношк, насчет включенного текстурирования.

};

namespace SGSystem
{
    	bool ConsoleRusificated      = false; //!< Показывает русифицирована консоль или нет. Нужна для функций, использующих printf.

    	int MouseX,                           //!< Позиция мыши по оси x
            MouseY;                           //!< Позиция мыши по оси y

    	int MouseWheel        = 0;            //!< Показывает на сколько повернуто колёсико мыши.

    	bool KeyPressed [256] = {};           //!< Показывает нажатые кнопки.		
};

const COLORREF 

#ifdef FOR_DOXYGEN_ONLY
enum SGColors {
#endif

    SG_BLACK         = RGB (  0,   0,   0),   //!< Черный цвет.
    SG_BLUE          = RGB (  0,   0, 128),   //!< Темно-синий цвет.
    SG_GREEN         = RGB (  0, 128,   0),   //!< Зеленый цвет.
    SG_CYAN          = RGB (  0, 148, 255),   //!< Бирюзовый цвет. Лучше, чем в TXLib ^-^.
    SG_RED           = RGB (128,   0,   0),   //!< Темно-красный цвет.
    SG_MAGENTA       = RGB (128,   0, 128),   //!< Темно-малиновый цвет.
    SG_BROWN         = RGB (127,  51,   0),   //!< Коричневый цвет. Лучше, чем в TXLib ^-^.
    SG_ORANGE        = RGB (255, 128,   0),   //!< Оранжевый цвет.
    SG_GRAY          = RGB (160, 160, 160),   //!< Серый цвет.
    SG_DARKGRAY      = RGB (128, 128, 128),   //!< Темно-серый цвет.
    SG_LIGHTGRAY     = RGB (192, 192, 192),   //!< Светло-серый цвет.
    SG_LIGHTBLUE     = RGB (  0,   0, 255),   //!< Светло-синий цвет.
    SG_LIGHTGREEN    = RGB (  0, 255, 128),   //!< Светло-зеленый цвет.
    SG_LIGHTCYAN     = RGB (  0, 255, 255),   //!< Светло-бирюзовый цвет.
    SG_LIGHTRED      = RGB (255,   0, 128),   //!< Светло-красный цвет.
    SG_LIGHTMAGENTA  = RGB (255,   0, 255),   //!< Светло-малиновый цвет.
    SG_PINK          = RGB (255, 167, 255),   //!< Розовый гламурный. Гламурней, чем в TXLib ^-^.
    SG_YELLOW        = RGB (255, 255, 128),   //!< Желтый цвет.
    SG_WHITE         = RGB (255, 255, 255),   //!< Белый цвет.
    SG_LIB           = 0xFF00FF;              //!< Традиционный цвет SGLib. Красивее, чем в EXLib)))

#ifdef FOR_DOXYGEN_ONLY
};
#endif

struct POINT3D
{
	int x_pos, //!< Позиция точки по X
	    y_pos, //!< Позиция точки по Y
	    z_pos; //!< Позиция точки по Z
};

class SGTexture
{
	GLuint _ADRES;
	bool Loaded;
	
	public:
};

struct SGVector
{
	int x,	//!< Позиция вектора по X
	    y,  //!< Позиция вектора по Y
	    z;  //!< Позиция вектора по Z
};

class SGCamera
{
	float SRM_ [16];
	float DRM_ [16];
	                   	
	SGVector ClickVector;
	SGVector DragVecor;

	bool Replaced;

	public:
};

bool sgOk(bool TestWindow = false, bool TestOpenGL = false);
bool sgCreateWindow(int width, int height, LPCSTR name);


bool sgOk(bool TestWindow /* = false*/, bool TestOpenGL /* = false*/)
{
    	if (TestWindow == true && SGWindow::WindowRun == false)                                return false;
    	if (TestOpenGL == true && SGWindow::OpenGLRun == false)                                return false;
    	if (SGWindow::WindowRun == true && (SGWindow::width < 1 || SGWindow::height < 1))      return false;

    	return true;
}

bool sgCreateWindow(int width, int height, LPCSTR name /* = SGWindow::WinDefTitle*/)
{
    SGWindow::width = width;
    SGWindow::height = height;

    SIZE frame   = {GetSystemMetrics (SM_CXFIXEDFRAME), GetSystemMetrics (SM_CYFIXEDFRAME)};

    SGWindow::WindowSx = width + 2 * frame.cx;
    SGWindow::WindowSy = height + 2 * frame.cy + GetSystemMetrics (SM_CYCAPTION);

    asserted (sgOk());
    asserted (!SGWindow::WindowRun);

    HINSTANCE hInstance = GetModuleHandle (NULL);
                        
    WNDCLASS WindowClass;
    WindowClass.style         = CS_OWNDC;
    WindowClass.lpfnWndProc   = sgWindowMessageProcess;
    WindowClass.cbClsExtra    = 0;
    WindowClass.cbWndExtra    = 0;
    WindowClass.hInstance     = hInstance;
    WindowClass.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
    WindowClass.hCursor       = LoadCursor (NULL, IDC_ARROW);
    WindowClass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
    WindowClass.lpszMenuName  = NULL;
    WindowClass.lpszClassName = name;
    RegisterClass (&WindowClass);
               
    int SSX = GetSystemMetrics (SM_CXSCREEN), SSY = GetSystemMetrics (SM_CYSCREEN);

    sgWindowParams::WND = CreateWindow (name, name, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE | WS_BORDER /* | WS_MAXIMIZEBOX | WS_MINIMIZEBOX */, (SSX - exWindowParams::RealSx) / 2, (SSY - exWindowParams::RealSy) / 2, exWindowParams::RealSx, exWindowParams::RealSy, NULL, NULL, hInstance, NULL);

    asserted (sgWindowParams::WND);

/*
    sgWindowParams::DC = GetDC (sgWindowParams::WND);

    sgWindow::WindowRun = true;

    #ifdef __TXLIB_H
        #define GetConsoleWindow Win32::GetConsoleWindow
    #endif

    HWND Console = GetConsoleWindow ();

    #ifdef __TXLIB_H
        #undef GetConsoleWindow
    #endif

    SIZE ConsoleSize = {sgWindow::WindowSx, (SSY - sgWindow::WindowSy) / 2 - 2 * frame.cy};

    if (sgWindow::WindowSx > 100 && (SSY - sgWindow::WindowSy) / 2 > 50)
    {
        MoveWindow (Console, (SSX - exWindowParams::RealSx) / 2, 0, ConsoleSize.cx, ConsoleSize.cy, true);
    }

    if (SGUser::Rusificate == true) sgRusificate ();

    sgEnableOpenGL ();

    if (SGUser::DepthTest == true) sgRun3DMode ();
    else                           sgRun2DMode ();

    glEnable(GL_COLOR_MATERIAL);
    sgLoadIdentity ();
    sgSetColor(SG_LIB);
    sgClear(0, 0, 0);
    asserted (sgOk());*/
}

/* Место куда ставить курсор перед сном на клаве

*/

#endif //SGLIB_H_INCLUDED 